package agent

import (
	"context"
	"fmt"
	"log"
	"strings"
	"sync"

	"openmanus/llm/history"

	"github.com/axcom/ninego/class"
	logger "github.com/axcom/ninego/log"
)

// AgentState represents the state of the agent.
type AgentState int

const (
	IDLE AgentState = iota
	RUNNING
	FINISHED
	ERROR
)

// IBaseAgent 所有代理的基础接口
type IBaseAgent interface {
	// 获取智能体信息
	GetDescription() string

	// Run 运行代理
	Run(ctx context.Context, request string) (string, error)

	// Step 执行单个步骤
	Step() (string, error)

	// UpdateMemory 更新代理的记忆
	UpdateMemory(role ROLE_TYPE, content string, kwargs ...map[string]interface{}) error

	// Cleanup 清理代理资源
	Cleanup() error
}

// BaseAgent is the abstract base class for managing agent state and execution.
type BaseAgent struct {
	class.Object                       //Class基类
	Name               string          //智能体的名称
	Description        string          //智能体的描述
	SystemPrompt       string          //系统提示词
	NextStepPrompt     string          //下一步提示词
	LLM                *LLMClient      //语言模型实例
	Memory             *history.Memory //智能体的记忆存储
	State              AgentState      //当前智能体状态（IDLE、RUNNING、FINISHED、ERROR）
	MaxSteps           int
	CurrentStep        int
	DuplicateThreshold int
	mu                 sync.Mutex
}

// NewBaseAgent creates a new BaseAgent instance.
func NewBaseAgent(name string, llm *LLMClient, memory *history.Memory) *BaseAgent {
	if llm.ConfigName == "" {
		llm.ConfigName = name
	}
	return class.Create(&BaseAgent{
		Name:               name,
		LLM:                llm,
		Memory:             memory,
		State:              IDLE,
		MaxSteps:           10,
		CurrentStep:        0,
		DuplicateThreshold: 2,
	})
}

// StateContext is a context manager for safe agent state transitions.
func (a *BaseAgent) StateContext(ctx context.Context, newState AgentState) func() {
	a.mu.Lock()
	defer a.mu.Unlock()

	if newState < IDLE || newState > ERROR {
		log.Fatalf("Invalid state: %v", newState)
	}

	previousState := a.State
	a.State = newState

	return func() {
		a.mu.Lock()
		defer a.mu.Unlock()
		a.State = previousState
	}
}

func (a *BaseAgent) GetDescription() string {
	return a.Description
}

// UpdateMemory 更新代理的记忆
func (a *BaseAgent) UpdateMemory(role ROLE_TYPE, content string, kwargs ...map[string]interface{}) error {
	ret, handled := a.Inherited(role, content, class.Variadic{kwargs})
	if handled {
		return class.SC[error](ret[0])
	}

	if len(kwargs) > 0 {
		msg := history.HistoryMessage{
			Role: string(role), //"tool",
			Content: []history.ContentBlock{{
				Type: "text",
				Text: content,
			}},
		}
		if tcID, ok := kwargs[0]["tool_call_id"].(string); ok {
			msg.Content[0].ID = tcID
		}
		if tcName, ok := kwargs[0]["name"].(string); ok {
			msg.Content[0].Name = tcName
		}
		if tcText, ok := kwargs[0]["text"].(string); ok {
			msg.Content[0].Text = tcText
		}
		a.Memory.Messages = append(a.Memory.Messages, msg)
		//msg = llm.Message{Role: TOOL, Content: content, ToolCallID: kwargs[0]}
	} else if content != "" {
		a.Memory.Messages = append(
			a.Memory.Messages,
			history.HistoryMessage{
				Role: string(role), //"user",
				Content: []history.ContentBlock{{
					Type: "text",
					Text: content,
				}},
			},
		)
	}
	return nil
}

// 执行智能体的主循环，在循环中不断调用step方法，直到任务完成或达到最大步骤数：
func (a *BaseAgent) Run(ctx context.Context, request string) (string, error) {
	ret, handled := a.Inherited(ctx, request)
	if handled {
		return class.SC[string](ret[0]), class.SC[error](ret[1])
	}

	fmt.Println("run...")
	a.CurrentStep = 0

	a.mu.Lock()
	if a.State != IDLE {
		a.mu.Unlock()
		return "", fmt.Errorf("无法从状态 %v 运行代理", a.State)
	}
	a.mu.Unlock()

	if a.SystemPrompt != "" {
		a.UpdateMemory(SYSTEM, a.SystemPrompt)
	}
	if request != "" {
		err := a.UpdateMemory(USER, request)
		if err != nil {
			return "", fmt.Errorf("更新记忆失败: %w", err)
		}
	}

	results := []string{}
	// 设置状态为运行中
	revertState := a.StateContext(ctx, RUNNING)
	defer func() {
		// 清理资源
		if err := a.Cleanup(); err != nil {
			logger.Error("清理代理资源时出错: %v", err)
		}

		revertState() // 恢复原始状态
	}()

	for a.CurrentStep < a.MaxSteps && a.State != FINISHED {
		a.CurrentStep++
		log.Printf("执行步骤 %d/%d", a.CurrentStep, a.MaxSteps)
		stepResult, err := a.Step()
		if err != nil {
			logger.Error("步骤执行失败: %v", err)
			return "", err
		}

		// 检查是否陷入循环
		if a.IsStuck() {
			a.HandleStuckState()
		}

		results = append(results, fmt.Sprintf("Step %d: %s", a.CurrentStep, stepResult))
	}

	// 如果达到最大步骤数，重置状态
	if a.CurrentStep >= a.MaxSteps {
		a.CurrentStep = 0
		defer a.StateContext(ctx, IDLE)() //a.State = IDLE
		results = append(results, fmt.Sprintf("终止: 已达到最大步骤数 (%d)", a.MaxSteps))
	}

	return strings.Join(results, "\n"), nil
}

// Step 执行单个步骤（需要子类实现）
func (a *BaseAgent) Step() (string, error) {
	ret, handled := a.Inherited()
	if handled {
		return class.SC[string](ret[0]), class.SC[error](ret[1])
	}

	// Implement the step logic here
	return "", fmt.Errorf("Step方法需要在子类中实现")
}

// IsStuck 检查代理是否陷入循环
func (a *BaseAgent) IsStuck() bool {
	messages := a.Memory.Messages
	if len(messages) < 2 {
		return false
	}

	lastMessage := messages[len(messages)-1]
	if lastMessage.GetContent() == "" {
		return false
	}

	// 计算相同内容的出现次数
	duplicateCount := 0
	for i := len(messages) - 2; i >= 0; i-- {
		msg := messages[i]
		if msg.GetRole() == ASSISTANT && msg.GetContent() == lastMessage.GetContent() {
			duplicateCount++
			if duplicateCount >= a.DuplicateThreshold {
				return true
			}
		}
	}

	return false
}

// HandleStuckState 处理陷入循环的状态
func (a *BaseAgent) HandleStuckState() {
	stuckPrompt := "观察到重复响应。请考虑新的策略，避免重复已经尝试过的无效路径。"
	a.NextStepPrompt = fmt.Sprintf("%s\n%s", stuckPrompt, a.NextStepPrompt)
	logger.Warn("代理检测到陷入循环状态。添加提示: %s", stuckPrompt)
}

// Cleanup 清理代理资源
func (a *BaseAgent) Cleanup() error {
	// 基础清理，子类可以扩展
	ret, handled := a.Inherited()
	if handled {
		return class.SC[error](ret[0])
	}

	return nil
}
